package com.zzl.finance.data.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzl.finance.data.constant.BlackListTypeEnum;
import com.zzl.finance.data.constant.EnterPriseGradeEnum;
import com.zzl.finance.data.constant.FinancierTypeConstant;
import com.zzl.finance.data.constant.UserCategoryConstant;
import com.zzl.finance.data.dao.EnterpriseRelationDao;
import com.zzl.finance.data.dto.*;
import com.zzl.finance.data.entity.EnterpriseEntity;
import com.zzl.finance.data.entity.EnterpriseRelationEntity;
import com.zzl.finance.data.entity.FinanceInstitutyEntity;
import com.zzl.finance.data.entity.feign.SupplierCreditEntity;
import com.zzl.finance.data.feign.BondsTicketFeign;
import com.zzl.finance.data.feign.UserCenterFeign;
import com.zzl.finance.data.service.EnterpriseRelationService;
import com.zzl.finance.data.service.EnterpriseService;
import com.zzl.finance.data.service.FinanceInstitutyService;
import com.zzl.general.common.exception.SysException;
import com.zzl.general.common.requestparameter.KeyAndValue;
import com.zzl.general.common.serurity.entity.User;
import com.zzl.general.common.utils.NumberUtil;
import com.zzl.general.common.utils.PageUtils;
import com.zzl.general.common.utils.Query;
import com.zzl.sharding.user.entity.UserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 企业关系表
 *
 * @author sunpp
 * @date 2021-11-30 13:12:59
 */
@Service("enterpriseRelationService")
public class EnterpriseRelationServiceImpl extends ServiceImpl<EnterpriseRelationDao, EnterpriseRelationEntity> implements EnterpriseRelationService {

    @Resource
    private EnterpriseService enterpriseService;

    @Resource
    private UserCenterFeign userCenterFeign;

    @Resource
    private FinanceInstitutyService financeInstitutyService;

    @Autowired
    private BondsTicketFeign bondsTicketFeign;

    /**
     * 分页查询 核心企业白名单
     *
     * @param params 查询参数
     * @return 分页数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageUtils queryWhitePage(Map<String, Object> params) throws SysException {
        IPage<BwShowDto> page = new Query<BwShowDto>().getPage(params, false);
        // 找到集团企业的id
        EnterpriseEntity coreGroup = enterpriseService.findCoreGroup();
        if (ObjectUtils.isEmpty(coreGroup)) {
            return new PageUtils(page);
        }
        params.put("isBlack", BlackListTypeEnum.WHITE_LIST_TYPE.getKey());
        IPage<BwShowDto> bwPage = this.baseMapper.getWhiteBlackPage(page, coreGroup.getId(), 0, params);
        List<BwShowDto> records = bwPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new PageUtils(page);
        }
        List<String> enterpriseIds = records.stream().map(BwShowDto::getEnterpriseId).distinct().collect(Collectors.toList());
        // 找出所有的 银行
        List<FinanceInstitutyEntity> financeInstitutyList = financeInstitutyService.list();
        if (CollectionUtils.isEmpty(financeInstitutyList)) {
            throw new SysException("当前 平台不存在金融机构");
        }
        // 用户服务的 feign 查找所有的 企业管理员的信息
        List<UserEntity> userEntities = userCenterFeign.getAdminInfo(enterpriseIds);
        for (BwShowDto dto : records) {
            // 设置银行 金融机构的信息
            setBankListButton(dto);
            if (!CollectionUtils.isEmpty(userEntities)) {
                userEntities.stream().filter(x -> x.getEnterpriseId().equals(dto.getEnterpriseId())).findFirst().ifPresent(
                        p -> {
                            dto.setUserName(p.getUserName());
                            dto.setUserPhone(p.getUserPhone());
                            dto.setEmail(p.getUserEmail());
                        }
                );
            }
        }
        return new PageUtils(bwPage);
    }

    /**
     * 设置按钮名称
     *
     * @param dto 额度对象
     */
    private void setBankListButton(BwShowDto dto) {
        if (dto.getIsBlackList().equals(0)) {
            dto.setButtonName("添加至黑名单");
        }
    }

    /**
     * 凭证融资额度
     *
     * @param financeInstitutyList 金融机构
     * @param creditEntities       授信
     * @return
     * @throws SysException 异常
     */
    private List<BwBankShowDto> setBankList(List<FinanceInstitutyEntity> financeInstitutyList, List<SupplierCreditEntity> creditEntities) {

        // 金融机构的集合
        List<BwBankShowDto> bankShowDtos = new ArrayList<>();
        for (FinanceInstitutyEntity financeInstituty : financeInstitutyList) {
            BwBankShowDto bankShowDto = new BwBankShowDto();
            bankShowDto.setCreditLimitFlag(Boolean.TRUE);
            // 设置 金融机构 给供应商的 开票额度
            if (!CollectionUtils.isEmpty(creditEntities)) {
                Optional<SupplierCreditEntity> creditEntityOptional = creditEntities.stream().filter(x -> x.getInstitutyId().equals(financeInstituty.getId())).findFirst();
                if (creditEntityOptional.isPresent()) {
                    SupplierCreditEntity creditEntity = creditEntityOptional.get();
                    bankShowDto.setId(creditEntity.getId());
                    Double creditAllAmount = creditEntity.getCreditAllAmount();
                    if (!ObjectUtils.isEmpty(creditAllAmount)) {
                        bankShowDto.setCreditLimitFlag(Boolean.FALSE);
                        //设置凭证融资限额
                        bankShowDto.setCreditAllAmount(creditAllAmount);
                        bankShowDto.setCreditUsedAmount(creditEntity.getCreditUsedAmount());
                        bankShowDto.setCreditSurplusAmount(NumberUtil.numberFormatString(creditEntity.getCreditSurplusAmount()));
                        bankShowDto.setUpdateTime(creditEntity.getUpdateTime());
                    }
                }
            }

            bankShowDto.setInstinctyName(financeInstituty.getInstinctyName());
            bankShowDto.setFinanceInstitutyId(financeInstituty.getId());
            bankShowDtos.add(bankShowDto);
        }
        return bankShowDtos;
    }

    @Override
    public PageUtils queryBlackPage(Map<String, Object> params) {
        IPage<BwShowDto> page = new Query<BwShowDto>().getPage(params, false);
        EnterpriseEntity coreGroup = enterpriseService.findCoreGroup();
        if (ObjectUtils.isEmpty(coreGroup)) {
            return new PageUtils(page);
        }
        params.put("isBlack", 1);
        IPage<BwShowDto> bwPage = this.baseMapper.getWhiteBlackPage(page, coreGroup.getId(), 1, params);
        if (CollectionUtils.isEmpty(bwPage.getRecords())) {
            return new PageUtils(page);
        }
        List<BwShowDto> records = bwPage.getRecords();
        List<String> enterpriseIds = records.stream().map(BwShowDto::getEnterpriseId).distinct().collect(Collectors.toList());
        List<UserEntity> userEntities = userCenterFeign.getAdminInfo(enterpriseIds);
        for (BwShowDto dto : bwPage.getRecords()) {
            if (dto.getIsBlackList().equals(0)) {
                dto.setButtonName("解除黑名单");
            }
            if (!CollectionUtils.isEmpty(userEntities)) {
                userEntities.stream().filter(x -> x.getEnterpriseId().equals(dto.getEnterpriseId())).findFirst().ifPresent(
                        p -> {
                            dto.setUserName(p.getUserName());
                            dto.setUserPhone(p.getUserPhone());
                            dto.setEmail(p.getUserEmail());
                        }
                );
            }
        }

        return new PageUtils(bwPage);
    }

    /**
     * 设置当前供应商为 黑白供应商
     *
     * @param dto  关系表主键id
     * @param user 登录用户
     * @return 提示信息
     * @throws SysException 业务异常
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String updateBw(SetBlackOrWhiteDto dto, User user) throws SysException {
        EnterpriseRelationEntity entity = this.getById(dto.getId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new SysException("未查到当前数据");
        }
        Integer isBlack = 0;
        if (entity.getIsBlacklist().equals(0)) {
            isBlack = 1;
        }
        entity.setUpdaterId(user.getId());
        entity.setUpdateTime(new Date());
        entity.setIsBlacklist(isBlack);
        if (!ObjectUtils.isEmpty(dto.getRemark())) {
            entity.setRemark(dto.getRemark());
        }
        this.updateById(entity);
        return isBlack.equals(0) ? "添加为白名单成功" : "添加为黑名单成功";
    }


    /**
     * 新增 黑名单或者 白名单数据 如果已经存在 则 给出提示 数据
     *
     * @param bwRelationAddDto 新增实体
     * @param user             当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void saveEnterpriseRelation(BwRelationAddDto bwRelationAddDto, User user) throws SysException {
        // 添加 白名单 验证企业评级
        if (BlackListTypeEnum.WHITE_LIST_TYPE.getKey().equals(bwRelationAddDto.getIsBlackList()) &&
                ObjectUtils.isEmpty(bwRelationAddDto.getEnterpriseGrade())) {
            throw new SysException("请设置企业评级");
        }
        EnterpriseEntity coreGroup = enterpriseService.findCoreGroup();
        if (ObjectUtils.isEmpty(coreGroup)) {
            throw new SysException("未查到 集团企业数据");
        }
        // 在集团下的 添加白名单或者黑名单 的企业是否 重复
        LambdaQueryWrapper<EnterpriseRelationEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 一个供应商与一个 父级供应商的 关系只能存在一种
        queryWrapper.eq(EnterpriseRelationEntity::getEnterpriseId, bwRelationAddDto.getEnterpriseId())
                .eq(EnterpriseRelationEntity::getEnterpriseParentId, coreGroup.getId());
        List<EnterpriseRelationEntity> list = this.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            throw new SysException("该供应商关系已存在");
        }
        EnterpriseRelationEntity entity = new EnterpriseRelationEntity();
        entity.setEnterpriseId(bwRelationAddDto.getEnterpriseId());
        // 核心企业id
        entity.setEnterpriseParentId(coreGroup.getId());
        // 获取登录用户的企业 id
        entity.setIsBlacklist(bwRelationAddDto.getIsBlackList());
        entity.setEnterpriseGrade(bwRelationAddDto.getEnterpriseGrade());
        entity.setDeletedStatus(0);
        entity.setRemark(bwRelationAddDto.getRemark());
        entity.setCreatorId(user.getId());
        entity.setUpdaterId(user.getId());
        entity.setOrgId(user.getOrgId());
        if (!this.save(entity)) {
            throw new SysException("A00001", "保存失败！");
        }
    }


    /**
     * 修改 企业评级
     *
     * @param enterpriseRelationUpdateDto 修改实体
     * @param user                        当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void updateEnterpriseRelationById(EnterpriseRelationUpdateDto enterpriseRelationUpdateDto, User user) throws SysException {
        // 非集团角色不可以 修改
        if (user.getUserCategory().equals(UserCategoryConstant.USER_CATEGORY_SUPPLIER.getKey())) {
            throw new SysException("当前用户,非集团或者核心企业角色无法修改");
        }

        EnterpriseRelationEntity relationEntity = new EnterpriseRelationEntity();
        // 企业id
        if (ObjectUtils.isEmpty(enterpriseRelationUpdateDto.getId())) {
            throw new SysException("参数错误，请填写id");
        }
        relationEntity.setId(enterpriseRelationUpdateDto.getId());
        // 企业 评级
        relationEntity.setEnterpriseGrade(enterpriseRelationUpdateDto.getEnterpriseGrade());

        if (!this.updateById(relationEntity)) {
            throw new SysException("A00002", "修改失败！");
        }
    }

    /**
     * 获取 企业评级的 枚举值
     *
     * @return 企业评级的枚举值
     */
    @Override
    public List<KeyValueDto> getEnterpriseGrade() {
        return EnterPriseGradeEnum.getEnumMap();
    }


    /**
     * 供应商相关接口
     */

    /**
     * 分页查询供应商 的下级供应商 关系表
     *
     * @param params 条件参数
     * @param user   登录用户
     * @return
     */
    @Override
    public PageUtils getSupplierRelationPage(Map<String, Object> params, User user) {
        IPage<SupplierRelationShowDto> page = new Query<SupplierRelationShowDto>().getPage(params, false);
        IPage<SupplierRelationShowDto> supplierRelationPage = this.baseMapper.getSupplierRelationPage(page, user.getEnterpriseId(), params);
        return new PageUtils(supplierRelationPage);
    }

    /**
     * 供应商管理 建立 平台上的 供应商 上下级关系
     * 1 只能添加 平台上的 供应商
     * 2 建立 上下级关系
     * 3 验证 一家企业只存在一条数据
     *
     * @param enterpriseId 下级供应商 企业id
     * @param user         当前登录用户
     * @throws SysException 业务异常
     */
    @Override
    public void addSubordinate(String enterpriseId, User user) throws SysException {
        EnterpriseEntity enterprise = enterpriseService.getById(enterpriseId);
        if (ObjectUtils.isEmpty(enterprise)) {
            throw new SysException("未在平台内找到该添加的企业 信息");
        }
        if (user.getEnterpriseId().equals(enterpriseId)) {
            throw new SysException("不能设置自己哦");
        }
        if (!user.getUserCategory().equals(UserCategoryConstant.USER_CATEGORY_SUPPLIER.getKey())) {
            throw new SysException("当前登录用户并非平台供应商");
        }
        LambdaQueryWrapper<EnterpriseRelationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(EnterpriseRelationEntity::getEnterpriseId, enterpriseId)
                // 当前企业为 父id
                .eq(EnterpriseRelationEntity::getEnterpriseParentId, user.getEnterpriseId());
        List<EnterpriseRelationEntity> list = this.list(queryWrapper);
        if (!CollectionUtils.isEmpty(list)) {
            throw new SysException("该供应商关系已存在");
        }

        EnterpriseRelationEntity relationEntity = new EnterpriseRelationEntity();
        relationEntity.setEnterpriseParentId(user.getEnterpriseId());
        relationEntity.setEnterpriseId(enterpriseId);
        relationEntity.setIsBlacklist(1);
        relationEntity.setDeletedStatus(0);
        relationEntity.setCreateTime(new Date());
        relationEntity.setUpdateTime(new Date());
        relationEntity.setCreatorId(user.getId());
        if (!this.save(relationEntity)) {
            throw new SysException("添加错误");
        }
    }

    /**
     * 解除 供应商关系
     *
     * @param relationId 供应商关系id
     */
    @Override
    public void deleteSupplierRelation(String relationId) {
        this.baseMapper.deleteById(relationId);
    }

    /**
     * 供应商列表-额度配置
     *
     * @param enterpriseId 供应商id
     * @return 额度配置列表
     */
    @Override
    public List<BwBankShowDto> quotaSetting(String enterpriseId) throws SysException {
        // 找出所有的 银行
        QueryWrapper<FinanceInstitutyEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FinanceInstitutyEntity::getFinancierType, FinancierTypeConstant.FINANCIER_TYPE_BANK.getKey());
        List<FinanceInstitutyEntity> financeInstitutyList = financeInstitutyService.list(queryWrapper);
        if (CollectionUtils.isEmpty(financeInstitutyList)) {
            throw new SysException("当前 平台不存在金融机构");
        }
        //可用融资额度
        Map<String, List<SupplierCreditEntity>> enterpriseQuota;
        // 供应商的凭证融资额度限制
        enterpriseQuota = bondsTicketFeign.getEnterpriseQuota(Arrays.asList(enterpriseId));

        // 当前 供应商的 金融机构给的开票额度
        List<SupplierCreditEntity> creditEntities = enterpriseQuota.get(enterpriseId);
        // 设置银行 金融机构的信息
        return setBankList(financeInstitutyList, creditEntities);
    }

    /**
     * 邀请链接
     *
     * @param user 用户
     * @return 链接
     */
    @Override
    public String getInvitationLink(HttpServletRequest request, User user) {
        StringBuffer requestURL = request.getRequestURL();
        String url = requestURL.toString();
        String baseUrl = url.substring(0, url.lastIndexOf("data") - 1);
        return baseUrl + "?invitationEnterpriseId=" + user.getEnterpriseId();
    }

    @Override
    public List<KeyAndValue> getAcquirerDropDownList(String ticketId, User user) {
        List<KeyAndValue> result=new ArrayList<>();
        List<String> transferableTicket = bondsTicketFeign.getAcquirerDropDownList(ticketId);
        QueryWrapper<EnterpriseRelationEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(EnterpriseRelationEntity::getEnterpriseParentId, user.getEnterpriseId())
                .eq(EnterpriseRelationEntity::getIsBlacklist, BlackListTypeEnum.WHITE_LIST_TYPE.getKey());
        if (transferableTicket == null) {
            queryWrapper.lambda().in(EnterpriseRelationEntity::getEnterpriseId, transferableTicket);
        }
        List<EnterpriseRelationEntity> enterpriseRelationEntities = baseMapper.selectList(queryWrapper);
        Collection<EnterpriseEntity> enterpriseEntities = enterpriseService.listByIds(enterpriseRelationEntities.stream()
                .map(EnterpriseRelationEntity::getEnterpriseId).collect(Collectors.toList()));
        enterpriseEntities.forEach(enterpriseEntity -> {
            KeyAndValue keyAndValue = new KeyAndValue(enterpriseEntity.getId(), enterpriseEntity.getEnterpriseName());
            result.add(keyAndValue);
        });
        return result;
    }

}